package org.apache.rocketmq.store;

import java.util.concurrent.atomic.AtomicLong;

/* @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
 * @author：陈清风扬，个人微信号：chenqingfengyangjj。
 * @方法描述：引用资源管理器
 */
public abstract class ReferenceResource {
    protected final AtomicLong refCount = new AtomicLong(0);

    protected volatile boolean available = true;

    protected volatile boolean cleanupOver = false;

    private volatile long firstShutdownTimestamp = 0;

    public synchronized boolean hold() {
        if (this.available) {
            if (this.refCount.getAndIncrement() >= 0) {
                return true;
            } else {
                this.refCount.decrementAndGet();
            }
        }
        return false;
    }

    public boolean isAvailable() {
        return this.available;
    }

    public void shutdown(long intervalForcibly) {
        if (this.available) {
            this.available = false;
            this.firstShutdownTimestamp = System.currentTimeMillis();
            this.release();
        } else if (this.getRefCount() > 0) {
            if (System.currentTimeMillis() - this.firstShutdownTimestamp >= intervalForcibly) {
                this.refCount.set(-1000 - this.getRefCount());
                this.release();
            }
        }
    }

    public void release() {
        //最终被释放的时候，也就是执行shutdown方法时，这里得到的value是0
        long value = this.refCount.decrementAndGet();
        if (value > 0) {
            return;
        }
        synchronized (this) {
            //代码就会执行到这里，执行清理内存映射资源操作
            this.cleanupOver = cleanup(value);
        }
    }

    protected abstract boolean cleanup(long value);

    public long getRefCount() {
        return this.refCount.get();
    }

    public boolean isCleanupOver() {
        return this.refCount.get() <= 0 && this.cleanupOver;
    }
}